package org.mayanjun.code.easyweb.springmvc.view;

import org.mayanjun.code.easyweb.springmvc.config.Global;
import org.mayanjun.code.easyweb.springmvc.util.UserAgentUtils;
import org.springframework.ui.Model;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Map;

/**
 * SmartView is actually a {@link ModelAndView}, but it provides some useful features, please check the following list:
 * <ul>
 *     <li>Support for the chain programming</li>
 *     <li>Support for device perception: tne view name will be set to "viewName-mobile" if it is turn on and the request is from a mobile device </li>
 * </ul>
 *
 * @author mayanjun
 * @since 0.0.2(Jan 15, 2016)
 *
 * @see UserAgentUtils
 * @see org.mayanjun.code.easyweb.springmvc.annotation.PerceiveDevice
 */
public class SmartView extends ModelAndView {

    public static final String MOBILE_VIEW_SUFFIX = "-mobile";
    private static final String DEFAULT_VIEW_NAME = "index";
    private boolean perceiveDevice;

    public SmartView() {
        this(false);
    }

    public SmartView(boolean perceiveDevice) {
        this(DEFAULT_VIEW_NAME, null, perceiveDevice);
    }

    public SmartView(String viewName, Model model, boolean perceiveDevice) {
        String vn = viewName;
        boolean pd = perceiveDevice;
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        if(!pd) {
            Object pdval = request.getAttribute(Global.REQUEST_ATTR_PERCEIVE_DEVICE_KEY);
            pd = (pdval != null && pdval instanceof Boolean && (Boolean)pdval);
        }
        if(pd) {
            if(UserAgentUtils.isMobilePlatform(request)) {
                String vp = request.getServletContext().getRealPath(Global.VELOCITY_VIEW_LOCATION + viewName + Global.VELOCITY_VIEW_SUFFIX);
                File file = new File(vp);
                if(file.exists() && file.canRead()) vn = viewName + MOBILE_VIEW_SUFFIX;
            }
        }
        this.setViewName(vn);
        if (model != null) {
            this.addAllObjects(model.asMap());
        }
    }

    public SmartView(Model model) {
        this(model, false);
    }

    public SmartView(Model model, boolean perceiveDevice) {
        this(DEFAULT_VIEW_NAME, model, perceiveDevice);
    }

    public SmartView(String viewName) {
        this(viewName, false);
    }

    public SmartView(String viewName, boolean perceiveDevice) {
        this(viewName, null, perceiveDevice);
    }

    public boolean isPerceiveDevice() {
        return perceiveDevice;
    }

    public void setPerceiveDevice(boolean perceiveDevice) {
        this.perceiveDevice = perceiveDevice;
    }

    @Override
    public SmartView addObject(String attributeName, Object attributeValue) {
        super.addObject(attributeName, attributeValue);
        return this;
    }

    @Override
    public SmartView addObject(Object attributeValue) {
        super.addObject(attributeValue);
        return this;
    }

    @Override
    public SmartView addAllObjects(Map<String, ?> modelMap) {
        super.addAllObjects(modelMap);
        return this;
    }
}
